package com.handpay.nocardpay.baselibrary.http;

import android.content.Context;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.google.gson.reflect.TypeToken;
import com.handpay.nocardpay.baselibrary.R;
import com.handpay.nocardpay.baselibrary.config.NoCardPayConfig;
import com.handpay.nocardpay.baselibrary.http.request.ByteRequest;
import com.handpay.nocardpay.baselibrary.http.request.GsonRequest;
import com.handpay.nocardpay.baselibrary.http.request.JsonArrayRequest;
import com.handpay.nocardpay.baselibrary.http.request.JsonObjectRequest;
import com.handpay.nocardpay.baselibrary.http.request.StringRequest;
import com.handpay.nocardpay.baselibrary.http.stack.OkHttp3Stack;
import com.handpay.nocardpay.baselibrary.logutils.HPLog;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.InputStream;

import okhttp3.OkHttpClient;

/**
 * @author sxshi
 */
public class HttpClientImpl {
    private static HttpClientImpl mInstance;
    private static RequestQueue mRequestQueue;
    private Context mContext;
    private boolean isDebug = false;
    public static final int DEFAULT_TIME_OUT = 90 * 1000; //default timeout

    private HttpClientImpl(Context context) {
        mContext = context.getApplicationContext();
        InputStream p12Keystore = mContext.getResources().openRawResource(R.raw.safesftclient);
        InputStream trustKeyStore = mContext.getResources().openRawResource(R.raw.safesftserver);
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (!isDebug) {//增加双向认证
            builder.sslSocketFactory(SSLCustomSocketFactory.getSocketFactory(p12Keystore, NoCardPayConfig.P12KEY, trustKeyStore));
        }
        //use okhttp http requst
        mRequestQueue = Volley.newRequestQueue(mContext, new OkHttp3Stack(builder.build()));

    }

    /**
     * init HttpClientImpl
     *
     * @param context
     * @return
     */
    public static void init(Context context) {
        if (null == mInstance) {
            synchronized (HttpClientImpl.class) {
                if (null == mInstance) {
                    mInstance = new HttpClientImpl(context);
                }
            }
        }
    }

    /**
     * @param request
     * @param tag
     */
    public static void addRequest(Request request, Object tag) {
        if (tag != null) {
            request.setTag(tag);
        }
        request.setRetryPolicy(new CustomRetryPolicy(DEFAULT_TIME_OUT));
        if (mRequestQueue != null) {
            mRequestQueue.add(request);
        } else {
            throw new IllegalArgumentException("RequestQueue is not initialized,please check your appaction!");
        }
    }

    /**
     * @param httpRequest
     * @param listener
     * @param tag
     * @return
     */
    public static Request request(HttpRequest httpRequest, HttpListener<String> listener, Object tag) {
        return null;
    }

    /**
     * cancelRequest
     *
     * @param tag
     */
    public static void cancelRequest(Object tag) {
        if (mRequestQueue != null) {
            mRequestQueue.cancelAll(tag);
        } else {
            throw new IllegalArgumentException("RequestQueue is not initialized,please check your appaction!");
        }
    }

    /**
     * http request return byte data
     *
     * @param httpRequest
     * @param listener
     * @param tag
     * @return
     */
    public static Request byteRequest(HttpRequest httpRequest, HttpListener<byte[]> listener, Object tag) {
        ByteRequest request = new ByteRequest(httpRequest, listener);
        HPLog.d(HPLog.TAG_RESULT, "url:" + request.getUrl());
        addRequest(request, tag);
        return request;
    }

    /**
     * String request
     * @param httpRequest
     * @param listener
     * @param tag
     * @return
     */
    public static Request stringRequest(HttpRequest httpRequest, HttpListener<String> listener, Object tag) {
        StringRequest request = new StringRequest(httpRequest, listener);
        HPLog.d(HPLog.TAG_RESULT, "url:" + request.getUrl());
        addRequest(request, tag);
        return request;
    }

    /**
     * http request Json Object
     *
     * @param httpRequest
     * @param listener
     * @param tag
     * @return
     */
    public static Request jsonObjectRequest(HttpRequest httpRequest, HttpListener<JSONObject> listener, Object tag) {
        JsonObjectRequest request = new JsonObjectRequest(httpRequest, listener);
        addRequest(request, tag);
        return request;
    }

    /**
     * http requst return JsonArray data
     *
     * @param httpRequest
     * @param listener
     * @param tag
     * @return
     */
    public static Request jsonArrayRequest(HttpRequest httpRequest, HttpListener<JSONArray> listener, Object tag) {
        JsonArrayRequest request = new JsonArrayRequest(httpRequest, listener);
        addRequest(request, tag);
        return request;
    }

    /**
     * http requst Gson data
     *
     * @param clzz
     * @param httpRequest
     * @param listener
     * @param tag
     * @param <T>
     * @return
     */
    public static <T> Request gsonRequest(Class<T> clzz, HttpRequest httpRequest, HttpListener<T> listener, Object tag) {
        HPLog.i(HPLog.YL_TAG, "gsonRequest url:" + httpRequest.getUrl());
        HPLog.i(HPLog.YL_TAG, "gsonRequest Headers:" + httpRequest.getHeaders().toString());
        HPLog.i(HPLog.YL_TAG, "gsonRequest Params:" + httpRequest.getParams().toString());
        GsonRequest<T> request = new GsonRequest<T>(clzz, httpRequest, listener);
        addRequest(request, tag);
        return request;
    }

    /**
     * http requst Gson data
     *
     * @param typeToken
     * @param httpRequest
     * @param listener
     * @param tag
     * @param <T>
     * @return
     */
    public static <T> Request gsonRequest(TypeToken<T> typeToken, HttpRequest httpRequest, HttpListener<T> listener, Object tag) {
        GsonRequest<T> request = new GsonRequest<T>(typeToken, httpRequest, listener);
        addRequest(request, tag);
        return request;
    }

}
